package com.zx.znav.controller.admin;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.zx.znav.bean.Navigation;
import com.zx.znav.constant.Constants;
import com.zx.znav.controller.vo.NavigationVO;
import com.zx.znav.error.BusinessException;
import com.zx.znav.error.EnumBusinessError;
import com.zx.znav.response.CommonReturnType;
import com.zx.znav.service.LinkService;
import com.zx.znav.service.NavigationService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;

import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author 挚爱之夕
 * @version 1.0
 * @implSpec 后台导航菜单管理
 * @since 2023-07-19 10:33
 */
@Controller
@RequestMapping("/admin/navigation")
public class NavigationController {
    @Autowired
    private NavigationService navigationService;
    @Autowired
    private LinkService linkService;

    //后台导航菜单管理页面
    @GetMapping
    public String index(Model model) {
        //查数据
        //一级导航
        List<Navigation> firstNavigations = navigationService.listFirstNavigation();
        //二级导航
        List<Navigation> secondNavigations = navigationService.listSecondNavigation();
        //二级导航菜单需要父级导航名称
        List<NavigationVO> secondNavigationVOs = secondNavigations.stream().map(this::convert).collect(Collectors.toList());
        model.addAttribute(Constants.FIRST_NAVIGATION_KEY, firstNavigations);
        model.addAttribute(Constants.SECOND_NAVIGATION_KEY, secondNavigationVOs);
        return "admin/navigation";
    }

    /**
     * do -> vo
     */
    public NavigationVO convert(Navigation navigation) {
        NavigationVO navigationVO = new NavigationVO();
        BeanUtils.copyProperties(navigation, navigationVO);
        //查父级导航名称
        LambdaQueryWrapper<Navigation> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Navigation::getId, navigation.getParentId());
        navigationVO.setParentNavName(navigationService.getOne(wrapper).getName());
        return navigationVO;
    }

    //新增导航菜单
    @PostMapping("/add")
    @Transactional
    @ResponseBody
    public Object add(Navigation navigation) throws BusinessException {
        try {
            boolean save = navigationService.save(navigation);
            if (!save) {  //添加失败
                throw new BusinessException(EnumBusinessError.OPERATOR_ERROR);
            }
            //如果是二级导航菜单，将其对应一级导航菜单linkCnt + 1
            if (navigation.getParentId() != null) {
                navigationService.operateLinkCntById(navigation.getParentId(), true);
            }
        } catch (Exception e) { //SQL异常，主键重复
            e.printStackTrace();
            throw new BusinessException(EnumBusinessError.NAME_EXISTS);
        }
        return CommonReturnType.create(navigation);
    }

    //根据id查询
    @GetMapping("/{id}")
    @ResponseBody
    public Object get(@PathVariable Integer id) {
        Navigation navigation = navigationService.getById(id);
        if (navigation.getParentId() != 0) {
            //二级导航菜单需要父级导航名称
            return CommonReturnType.create(convert(navigation));
        } else {
            return CommonReturnType.create(navigation);
        }
    }

    /**
     * 根据id更新
     */
    @PutMapping("/update")
    @ResponseBody
    public Object update(Navigation navigation) throws BusinessException {
        navigation.setUpdateTime(new Date());
        try {
            navigationService.updateById(navigation);
        } catch (Exception e) { //更新失败
            throw new BusinessException(EnumBusinessError.NAME_EXISTS);
        }
        return CommonReturnType.create(navigation);
    }

    //根据id删除
    @DeleteMapping("/delete/{id}")
    @Transactional
    @ResponseBody
    public Object delete(@PathVariable Integer id) throws BusinessException {
        //如果是一级导航，其下没有次级导航才能删除
        int count = navigationService.countSecondNavByFirstNavId(id);
        if (count > 0) {
            throw new BusinessException(EnumBusinessError.CHILD_NAV_EXISTS);
        }
        //如果是二级导航，其下没有链接才可删除
        Navigation navigation = navigationService.getById(id);
        if (navigation.getParentId() != null && navigation.getParentId() != 0) {//二级菜单
            Integer linkCnt = linkService.countLinkByByFirsNavIdAndSecondNavId(navigation.getParentId(), navigation.getId());
            if(linkCnt > 0){
                throw new BusinessException(EnumBusinessError.ATTACHED_LINK_EXISTS);
            }
            navigationService.removeById(id);
            //如果是二级导航菜单，将其对应一级导航菜单linkCnt - 1
            navigationService.operateLinkCntById(navigation.getParentId(), false);
        }else{
            navigationService.removeById(id);
        }
        return CommonReturnType.create("删除成功");
    }
    /*搜索*/

    /**
     * 搜索导航菜单
     *
     * @param navigation 1.根据导航菜单名模糊搜索
     *                   2.根据导航菜单上级菜单id查询
     * @return
     */
    @GetMapping("/search1")
    @ResponseBody
    public Object search1(Navigation navigation) {
        return CommonReturnType.create(navigationService.searchFirstNavigation(navigation));
    }

    @GetMapping("/search2")
    @ResponseBody
    public Object search2(Navigation navigation) {
        List<Navigation> navigations = navigationService.searchSecondNavigation(navigation);
        //需要父级导航名称
        List<NavigationVO> voList = navigations.stream().map(this::convert).collect(Collectors.toList());
        return CommonReturnType.create(voList);
    }

    /*页面更新*/
    //获取一级导航数据，更新前端下拉列表
    @GetMapping("/firstNav")
    @ResponseBody
    public Object firstNav() {
        return CommonReturnType.create(navigationService.listFirstNavigation());
    }

    //获取二级导航数据，更新二级导航表格
    @GetMapping("/secondNav")
    @ResponseBody
    public Object secondNav() {
        List<Navigation> secondNavigation = navigationService.listSecondNavigation();
        List<NavigationVO> voList = secondNavigation.stream().map(this::convert).collect(Collectors.toList());
        return CommonReturnType.create(voList);
    }
}
